package com.autonavi.collapse.task.model;

import java.util.*;

public class ExtendedMap {

    private String name;

    private Map<String, ConfigValue> configs = new HashMap<>();

    private ExtendedMapIndex index = new ExtendedMapIndex();

    private boolean readOnly = false;

    public ExtendedMap() {
    }

    public ExtendedMap(Map<String, ConfigValue> initConfigs) {
        this.configs.putAll(configs);
        for (String configKey : initConfigs.keySet()) {
            index.addIndex(configKey, configKey);
        }
        readOnly = true;
    }

    public ExtendedMap(String name, Map<String, ConfigValue> configs) {
        this.name = name;
        this.configs = configs;
    }

    public void setValue(String key, Object value) {
        if (!readOnly && value != null) {
            configs.put(key, new ConfigValue(value));
            index.addIndex(key, key);
        }
    }

    public String getStringValue(String key) {
        Object config = getValue(key);
        if (config != null) {
            return config.toString();
        }
        return null;
    }

    public String getStringValue(String key, String defaultValue) {
        String value = getStringValue(key);
        if (value != null) {
            return value;
        }
        return defaultValue;
    }

    public Integer getIntValue(String key) {
        Object config = getValue(key);
        if (config != null) {
            if (config instanceof Number) {
                return ((Number) config).intValue();
            } else if (config.getClass().isPrimitive()) {
                return (int) config;
            } else {
                return Integer.valueOf(config.toString());
            }
        }
        return null;
    }

    public Integer getIntValue(String key, int defaultValue) {
        Integer value = getIntValue(key);
        if (value != null) {
            return value;
        }
        return defaultValue;
    }

    public Long getLongValue(String key) {
        Object config = getValue(key);
        if (config != null) {
            if (config instanceof Number) {
                return ((Number) config).longValue();
            } else if (config.getClass().isPrimitive()) {
                return (long) config;
            } else if (config instanceof Date) {
                return ((Date) config).getTime();
            } else {
                return Long.valueOf(config.toString());
            }
        }
        return null;
    }

    public long getLongValue(String key, int defaultValue) {
        Long value = getLongValue(key);
        if (value != null) {
            return value;
        }
        return defaultValue;
    }

    public <T> List<T> getListValue(String key, Class<T> type) {
        Object config = configs.get(key);
        if (config != null) {
            return (List<T>) config;
        }
        return null;
    }

    public Object getValue(String key) {
        ConfigValue configValue = configs.get(key);
        if (configValue != null) {
            return configValue.getValue();
        }
        return null;
    }

    public ConfigValue getConfigValue(String key) {
        return configs.get(key);
    }

    public ExtendedMap getNestedMap(String key) {
        ExtendedMapIndex index = this.index.getIndex(key);
        if (index != null) {
            Map<String, ConfigValue> result = new HashMap<>();
            Map<String, String> childrenValues = index.getChildrenValues();
            for (Map.Entry<String, String> entry : childrenValues.entrySet()) {
                result.put(entry.getKey(), configs.get(entry.getValue()));
            }
            return new ExtendedMap(result);
        }
        return null;
    }

    public Map<String, ConfigValue> getAll() {
        return new HashMap<>(configs);
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String toString() {
        return configs.toString();
    }
}